package com.sychip.fhc.app.pref

import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.emptyPreferences
import androidx.datastore.preferences.core.stringPreferencesKey
import com.fhc.usb.UsbDeviceDto
import com.sychip.fhc.AppType
import com.sychip.fhc.app.wsn.screen.FilterDto
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.map
import timber.log.Timber
import java.io.IOException
import javax.inject.Inject

class PrefDataStoreImpl @Inject constructor(
    private val ds: DataStore<Preferences>
) : PrefDataStoreIf {

    companion object {
        val FIRST_LAUNCH = booleanPreferencesKey("first_launch")
        val APP_TYPE = stringPreferencesKey("APP_TYPE")
        val USB_ID = stringPreferencesKey("USB_ID")
        val RemindNotTablet = booleanPreferencesKey(ForTabletReminderMe)
    }

    override fun getFirstLaunch(): Flow<Boolean> {
        return ds.data.catch { e ->
            if (e is IOException) {
                emit(emptyPreferences())
            } else {
                throw e
            }
        }.map {
            val firstLaunch = it[FIRST_LAUNCH] != false
            firstLaunch
        }
    }

    override suspend fun saveFirstLaunch(isFirstLaunch: Boolean) {
        ds.edit {
            it[FIRST_LAUNCH] = isFirstLaunch
        }
    }

    override suspend fun getAppType(): AppType {
         val data =
             ds.data.map { preferences ->
                 preferences[APP_TYPE] // 直接获取key2对应的值
             }.firstOrNull()
        Timber.i(">>>getAppType PrefDataStoreImpl    ${data}")
        return AppType.fromValue(data)

    }

    override suspend fun saveAppType(appType: AppType) {
        ds.edit {
            it[APP_TYPE] = appType.toString()
        }
    }


    override  fun getRssiFilter(): Flow<String> {
        val filterKey = stringPreferencesKey(RssiFilterKey)
        return ds.data.catch { e ->

        }.map {it ->
            val filter = it[filterKey]
            filter ?: ""
        }


    }

    override suspend fun saveRssiFilter(filter: String) {
        val filterKey = stringPreferencesKey(RssiFilterKey)
        ds.edit {
            it[filterKey] = filter
        }
    }

    override fun getFilterDto(): Flow<FilterDto?> {
        val filterKey = stringPreferencesKey(FilterKey)
        return ds.data.catch { e ->
            if (e is IOException) {
                emit(emptyPreferences())
            } else {
                throw e
            }
        }.map {it ->
            val json = it[filterKey]
            if(json != null) filterJsonAdapter.fromJson(json) as FilterDto
            else null
        }
    }

    override suspend fun saveFilterDto(json: FilterDto) {
        val filterKey = stringPreferencesKey(FilterKey)
        ds.edit {
            it[filterKey] = filterJsonAdapter.toJson(json)
        }
    }
    override fun getMapSizeChangeReminderMe(): Flow<Boolean> {
        val rmKey = booleanPreferencesKey(MapSizeChangeReminderMe)
        return ds.data.catch { e ->
            Timber.e("PrefDataStoreImpl getMapSizeChangeReminderMe Flow %s ",e.message)
            true
        }.map {it ->
            val remind = it[rmKey]
            remind ?: true
        }
    }

    override suspend fun saveMapSizeChangeReminderMe(remind: Boolean) {
        val rmKey = booleanPreferencesKey(MapSizeChangeReminderMe)
        ds.edit {
            it[rmKey] = remind
        }
    }


    override suspend fun getRemindNotTablet(): Boolean {
        val data = ds.data.map { preferences -> preferences[RemindNotTablet]}.firstOrNull()
        return data ?: true
    }

    override suspend fun setRemindNotTablet(remind: Boolean) {
        ds.edit {
            it[RemindNotTablet] = remind
        }
    }

    override suspend fun getCurrentUsbId(): String{
        val data =
            ds.data.map { preferences ->
                preferences[USB_ID] // 直接获取key2对应的值
            }.firstOrNull()
        return data ?: ""

    }

    override suspend fun setCurrentUsbId(usbId:String){
        ds.edit {
            it[USB_ID] = usbId
        }
    }

    override fun getACStatus(devId: String): Flow<ACStatus> {
        val devIdKey = stringPreferencesKey(devId)
        return ds.data.catch { e ->
            if (e is IOException) {
                emit(emptyPreferences())
            } else {
                throw e
            }
        }.map {it ->
            val jsonString = it[devIdKey]
            if(jsonString != null) acJsonAdapter.fromJson(jsonString) as ACStatus
            else ACStatus()
        }
    }

    override suspend fun saveACStatus(devId: String, json: ACStatus) {
        val devIdKey = stringPreferencesKey(devId)
        ds.edit {
            it[devIdKey] = acJsonAdapter.toJson(json)
        }

    }

    override fun getAppSettings(): Flow<AppSetting> {
        val appSettingKey = stringPreferencesKey(AppSettingKey)
        return ds.data.catch { e ->
            if (e is IOException) {
                emit(emptyPreferences())
            } else {
                throw e
            }
        }.map {it ->
            val json = it[appSettingKey]
            if(json != null) appSettingJsonAdapter.fromJson(json) as AppSetting
            else AppSetting()
        }
    }

    override suspend fun saveAppSettings(json: AppSetting) {
        val appSettingKey = stringPreferencesKey(AppSettingKey)
        ds.edit {
            val  str = appSettingJsonAdapter.toJson(json)
            it[appSettingKey] = str
        }
    }

    override fun getUsbDevice(): Flow<UsbDeviceDto?> {
        val usbDeviceKey = stringPreferencesKey(UsbDeviceKey)
        return ds.data.catch { e ->
            if (e is IOException) {
                emit(emptyPreferences())
            } else {
                throw e
            }
        }.map {it ->
            val json = it[usbDeviceKey]
            if(json != null) usbDeviceJsonAdapter.fromJson(json) as UsbDeviceDto
            else null
        }
    }

    override suspend fun saveUsbDevice(json: UsbDeviceDto) {
        val appSettingKey = stringPreferencesKey(UsbDeviceKey)
        ds.edit {
            it[appSettingKey] = usbDeviceJsonAdapter.toJson(json)
        }
    }

    override fun compareUsbDevice(usb1: UsbDeviceDto, usb2: UsbDeviceDto): Boolean {
        return usb1.serialNumber ==  usb2.serialNumber
//        return usbDeviceJsonAdapter.toJson(usb1) ==  usbDeviceJsonAdapter.toJson(usb2)
    }
}